package common

import (
	"crypto/ecdsa"
	"crypto/elliptic"
	"crypto/rand"
	"fmt"
	"github.com/dgrijalva/jwt-go"
	"math/big"
)

const (
	//ES256 keys
	//ECDSAKeyD = "94B0E205FE7C36D766EE09515D433916D1990B8A3CE403FEE2E6E2AFE1B033B2"
	//ECDSAKeyX = "1857CAF0C10197F75EBBA249FDDF848ACD607578CF574121A88F5BA1DFB82971"
	//ECDSAKeyY = "3CD21F1AED372BE95467892BAFAA6E164F0B85F11E8AF30F0CC2FAFF38DC986E"
	ECDSAKeyD="CCFDFDC9C2572D15C639D07E3C6C8804A1E941B13F5D10C7297A2DFAA70E6393"
	ECDSAKeyX="EE4C3E11EB1BF081CFD4B5CCC482E069BFBECA07D566238F29191716319B809E"
	ECDSAKeyY="A40CCD993EC355326588E2A9E202C24A2D5D1BE5128B19885FD9F2C4155C3EF1"
)

//生成jwt key
func AdminCreateJwtKey() {
	randKey:=rand.Reader
	var err error
	prk, err := ecdsa.GenerateKey(elliptic.P256(), randKey)
	if err!=nil{
		fmt.Println("generate key error",err)
	}
	fmt.Printf("prkD=%X\n",prk.D)
	fmt.Printf("prkX=%X\n",prk.X)
	fmt.Printf("prkY=%X\n",prk.Y)
}

//获取签名算法为ES256的token
//该token的内容只有Redis的key,用于保存用户的登录状态
func JwtCreateToken(redisValue string) string {
	keyD := new(big.Int)
	keyX := new(big.Int)
	keyY := new(big.Int)

	keyD.SetString(ECDSAKeyD, 16)
	keyX.SetString(ECDSAKeyX, 16)
	keyY.SetString(ECDSAKeyY, 16)

	claims := jwt.MapClaims{
		"redisValue": redisValue,
	}

	token := jwt.NewWithClaims(jwt.SigningMethodES256, claims)
	publicKey := ecdsa.PublicKey{
		Curve: elliptic.P256(),
		X:     keyX,
		Y:     keyY,
	}

	privateKey := ecdsa.PrivateKey{D: keyD, PublicKey: publicKey}

	ss, err := token.SignedString(&privateKey)
	if err != nil {
		fmt.Println("ES256的token生成签名错误,err=%v", err)
		return ""
	}
	return ss
}

//解析签名算法为ES256的token
func JwtParseToken(tokenES string) string {
	keyX := new(big.Int)
	keyY := new(big.Int)

	keyX.SetString(ECDSAKeyX, 16)
	keyY.SetString(ECDSAKeyY, 16)

	publicKey := ecdsa.PublicKey{
		Curve: elliptic.P256(),
		X:     keyX,
		Y:     keyY,
	}

	token, err := jwt.Parse(tokenES, func(token *jwt.Token) (interface{}, error) {
		if _, ok := token.Method.(*jwt.SigningMethodECDSA); !ok {
			return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"])
		}
		return &publicKey, nil
	})
	if err != nil {
		fmt.Println("ES256的token解析错误,err=%v", err)
		return ""
	}

	if claims, ok := token.Claims.(jwt.MapClaims); ok {
		return claims["redisValue"].(string)
	}

	fmt.Println("ParseEStoken:Claims类型转换失败")
	return ""
}

